#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <malloc.h>
#include <assert.h>
#include "terrain.h"

void initBloc (bloc *newBloc)
{
	assert (newBloc != NULL);
	newBloc->dim = 0;
	newBloc->solide = 0;
	newBloc->pos.x = 0;
	newBloc->pos.y = 0;
	newBloc->typeBloc = ' ';
}

void supprimeBloc (bloc *oldBloc)
{
	assert (oldBloc != NULL);
	free (oldBloc);
}

void initTerrain (terrain *newTerrain)
{
    int i = 0;
    assert (newTerrain);
	newTerrain->hauteur = 0;
	newTerrain->largeur = 0;
	newTerrain->tab = NULL;
	while (i < 3)
    {
        newTerrain->CP[i] = 0;
        i++;
    }
}
/*
void supprimeTerrain (terrain *oldTerrain)
{
	free (oldTerrain);
}
*/
void setBloc (bloc *newBloc, int dim, int solide, char c)
{
	assert (newBloc != NULL);
	assert (dim > 0);
	assert (solide >= 0 && solide <=2);
	newBloc->dim = dim;
	newBloc->solide = solide;
	newBloc->typeBloc = c;
}

void copieBloc (bloc* B1, bloc* B2)
{
	assert (B1 != NULL);
	setBloc (B2, B1->dim, B1->solide, B1->typeBloc);
}

void setTerrain (terrain *Niveau, char* nomMap, const int dimBloc)
{
	int i, j, k = 0;
	char c;
	FILE* map = fopen (nomMap, "r");
	assert (Niveau != NULL);
	fscanf (map,"%d %d\n", &Niveau->largeur, &Niveau->hauteur);
	Niveau->tab = (bloc***) malloc (Niveau->hauteur*sizeof(bloc**));
	for (i=0 ; i<Niveau->hauteur ; i++)
	{
		Niveau->tab[i] = (bloc**) malloc (Niveau->largeur*sizeof(bloc*));
		for (j=0 ; j<Niveau->largeur ; j++)
		{
			Niveau->tab[i][j] = (bloc*) malloc (sizeof(bloc));
			fscanf(map, "%c", &c);
			initBloc (Niveau->tab[i][j]);
			if (c == ' ' || c == '0' || c == 'o'
				|| c == 'b' || c == 'g' || c == 'd'
				|| c == 'k' || c == 'l' || c == 's'
				|| c == 't' || c == 'a' || c == 'C')
			{
				setBloc (Niveau->tab[i][j], dimBloc, 0, c);
				if (c == 'C')
                {
                    Niveau->CP[k] = i;
                    k++;
                }
			}
			else if (c != '#')
			{
				setBloc (Niveau->tab[i][j], dimBloc, 1, c);
			}
			else
			{
				setBloc (Niveau->tab[i][j], dimBloc, 2, c);
			}
			Niveau->tab[i][j]->pos.x = j*32;
			Niveau->tab[i][j]->pos.y = i*32;
		}
		fscanf(map, "%c", &c);
	}
	fclose (map);
}

void setPosition (bloc* hitBox, const int x, const int y)
{
	assert (hitBox != NULL);
	assert (x >= 0 && y >= 0);
	hitBox->pos.x = x;
	hitBox->pos.y = y;
}

void blocMouvement (bloc* hitBox, const int x, const int y)
{
	assert (hitBox != NULL);
	hitBox->pos.x += x;
	hitBox->pos.y += y;
}

float getPositionX (bloc* hitBox)
{
	assert (hitBox != NULL);
	return hitBox->pos.x;
}

float getPositionY (bloc* hitBox)
{
	assert (hitBox != NULL);
	return hitBox->pos.y;
}

void videTerrain (terrain* Niveau)
{
	assert (Niveau != NULL);
	assert (Niveau->tab != NULL);
	int i, j;
	for (i = 0 ; i < Niveau->hauteur ; i++)
	{
		for (j = 0 ; j < Niveau->largeur ; j++)
		{
			supprimeBloc (Niveau->tab[i][j]); /* On libere l'espace pris par les blocs */
		}
		free (Niveau->tab[i]); /* On libere l'espace pris par chaque ligne du niveau */
	}
	free (Niveau->tab); /* On libere l'espace pris par la hauteur du tableau */
	initTerrain (Niveau);
}

void terrainTestRegression()
{
	terrain Niveau;
	bloc B1, B2, hitBox;

	initBloc(&B1);

	/* Verification de initBloc */
	if (B1.dim != 0 || B1.solide != 0 || B1.pos.x != 0 || B1.pos.y != 0 || B1.typeBloc != ' ')
	{
		printf("Problème d'initialisation avec initBloc...\n\n");
	}
	else
	{
		printf("initBloc est OK ! \n\n");
	}

	initBloc(&B2);
	initBloc(&hitBox);
	initTerrain (&Niveau);

	/* Verification de initTerrain */
	if (Niveau.hauteur != 0 ||Niveau.largeur != 0 || Niveau.tab != NULL)
	{
		printf ("Problème d'initialisation avec initTerrain...\n\n");
	}
	else
	{
		printf("initTerrain est OK !\n\n");
	}

	setBloc (&B1, 10, 1, 'T');

	/* Verification de setBloc */
	if (B1.dim !=10 || B1.solide != 1 || B1.typeBloc != 'T')
	{
		printf("Il y a un souci avec setBloc...\n\n");
	}
	else
	{
		printf("setBloc est OK !\n\n");
	}

	setBloc (&hitBox, 10, 1, 'P');
	copieBloc (&B1, &B2);
	/* Verification de copieBloc */
	if (B2.dim !=10 || B2.solide != 1 || B2.typeBloc != 'T')
	{
		printf("Il y a un souci avec copieBloc...\n\n");
	}
	else
	{
		printf("copieBloc est OK !\n\n");
	}

	setTerrain(&Niveau, "terrain.txt", 32);

	/* Verification de setTerrain */
	if (Niveau.largeur != 100 || Niveau.hauteur != 15)
	{
		printf("Probleme avec setTerrain...\n\n");
	}
	else if (Niveau.tab[7][30] == NULL)
	{
		printf("Probleme d'allocation des cases avec setTerrain...\n\n");
	}
	else if (Niveau.tab[14][99]->typeBloc != '#' || Niveau.tab[2][30]->typeBloc != ' ' || Niveau.tab[8][16]->typeBloc != 'T')
	{
		printf("Probleme de lecture du fichier dans setTerrain...\n\n");
	}
	else if (Niveau.tab[8][16]->solide != 1 || Niveau.tab[2][30]->solide != 0)
	{
		printf("Probleme avec l'attribution de la solidite dans setTerrain...\n\n");
	}
	else
	{
		printf("setTerrain est OK !\n\n");
	}

	setPosition(&hitBox, 10, 10);

	/* Verification de setPosition */
	if (hitBox.pos.x != 10 || hitBox.pos.y != 10)
	{
		printf("Problème avec setPosition...\n\n");
	}
	else
	{
		printf("setPosition est OK !\n\n");
	}

	blocMouvement (&hitBox, 10, 10);
	blocMouvement (&hitBox, 5, 5);

	/* Verification de blocMouvement */
	if (hitBox.pos.x != 25 || hitBox.pos.y != 25)
	{
		printf("Problème avec blocMouvement...\n\n");
	}
	else
	{
		printf("blocMouvement est OK !\n\n");
	}

	/* Verification de getPositionX et getPositionY */
	if (getPositionX (&hitBox) != 25)
	{
		printf ("Problème avec getPositionX...\n\n");
	}
	else if (getPositionY (&hitBox) != 25)
	{
		printf("Problème avec getPositionY...\n\n");
	}
	else
	{
		printf ("getPositionX et getPositionY sont OK ! \n\n");
	}

	videTerrain (&Niveau);

	if (Niveau.tab != NULL || Niveau.hauteur != 0 || Niveau.largeur != 0)
	{
		printf("Problème avec videTerrain...\n\n");
	}
	else
	{
		printf ("videTerrain et supprimeBloc sont OK ! \n\n");
	}

}


